﻿using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;

using MyCtp;
using MyCtp.Model;
using WAF.EntityFramework;
using CtpTrader.Core.Entity;
using CtpTrader.Core.Common;

namespace CtpTrader.Core.Trade
{
    /// <summary>
    /// 交易操作接口(所有事件为异步调用)
    /// </summary>
    public class Trader
    {
        /******************************** Field ********************************/

        #region variable

        /// <summary>
        /// 请求序号
        /// </summary>
        private int requestID = 0;

        /// <summary>
        /// 前置编号
        /// </summary>
        private int frontID = 0;

        /// <summary>
        /// 会话编号
        /// </summary>
        private int sessionID = 0;

        /// <summary>
        /// 报单引用
        /// </summary>
        private int orderRef = 0;

        /// <summary>
        /// 交易接口对象
        /// </summary>
        private CtpTdApi ctpTdApi;

        /// <summary>
        /// CTP账号
        /// </summary>
        private Account account;

        /// <summary>
        /// 要交易的单据
        /// </summary>
        private List<Order> orders;

        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="account">关联的CTP账户（一个交易接口实例只能对应一个账户）</param>
        /// <param name="fronts">前置机地址</param>
        public Trader(Account account)
        {
            this.account = account;

            this.orders = new List<Order>();

            Init();
        }

        /// <summary>
        /// 释放交易接口对象
        /// </summary>
        public void Release()
        {
            this.ctpTdApi.Release();
        }


        /******************************** 交易函数 ********************************/

        /// <summary>
        /// 开仓
        /// </summary>
        /// <param name="position">持仓类</param>
        /// <param name="detail">持仓明细类</param>
        public void Open(Position position, PositionDetail detail)
        {
            //开仓方向
            DirectionEnum direction = position.DirectionType == DirectionType.Buy ? DirectionEnum.Buy : DirectionEnum.Sell;

            this.InsertOrder(direction, MyOffsetFlag.Open, position.Security.Code, detail.Price, detail.OrderVolume);
        }

        /// <summary>
        /// 平仓
        /// </summary>
        /// <param name="position">持仓类</param>
        /// <param name="detail">持仓明细类</param>
        public void Close(Position position, double price, int volume)
        {
            //平仓使用相反方向
            DirectionEnum direction = position.DirectionType == DirectionType.Buy ? DirectionEnum.Sell : DirectionEnum.Buy;

            this.InsertOrder(direction, MyOffsetFlag.CloseToday, position.Security.Code, price, volume);
        }

        /// <summary>
        /// 发送报单
        /// </summary>
        /// <param name="direction">方向</param>
        /// <param name="offset">开平标志</param>
        /// <param name="code">合约代码</param>
        /// <param name="price">价格</param>
        /// <param name="volume">数量</param>
        private void InsertOrder(DirectionEnum direction, string offset, string code, double price, int volume)
        {
            CtpOrder ctpOrder = new CtpOrder();
            ctpOrder.Volume   = volume;
            ctpOrder.OrderRef = this.orderRef.ToString();
            orders.Add(ctpOrder);

            CThostFtdcInputOrderField order = new CThostFtdcInputOrderField();

            order.UserID                = this.account.Number;
            order.BrokerID              = this.account.BrokerCode;
            order.InvestorID            = this.account.Number;

            order.Direction             = direction;
            order.InstrumentID          = code;
            order.LimitPrice            = price;
            order.VolumeTotalOriginal   = volume;

            order.CombOffsetFlag        = offset;
            order.CombHedgeFlag         = MyHedgeFlag.Speculation;

            order.StopPrice             = 0;
            order.MinVolume             = 1;
            order.TimeCondition         = TimeConditionEnum.IOC;
            order.OrderPriceType        = OrderPriceTypeEnum.LimitPrice;
            order.VolumeCondition       = VolumeConditionEnum.AV;
            order.ContingentCondition   = ContingentConditionEnum.Immediately;

            order.RequestID             = requestID;
            order.OrderRef              = (this.orderRef++).ToString();

            order.IsAutoSuspend         = 0;
            order.UserForceClose        = 0;
            order.ForceCloseReason      = ForceCloseReasonEnum.NotForceClose;

            ctpTdApi.ReqOrderInsert(order, requestID++);
        }

        /// <summary>
        /// 报单操作（修改/撤销委托）
        /// </summary>
        /// <param name="action">操作类型呢（修改/删除）</param>
        /// <param name="orderRef">报单引用</param>
        /// <param name="instrumentID">合约代码</param>
        /// <param name="price">价格</param>
        /// <param name="volume">数量</param>
        public void OrderAction(ActionFlagEnum action, string orderRef, string instrumentID, double price, int volume)
        {
            CThostFtdcInputOrderActionField field = new CThostFtdcInputOrderActionField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;
            field.UserID = this.account.Number;
            field.InstrumentID = instrumentID;

            field.ActionFlag = action;
            field.LimitPrice = price;
            field.VolumeChange = volume;

            //报单在CTP平台用的定位
            field.FrontID = frontID;
            field.SessionID = sessionID;
            field.OrderRef = orderRef;

            //报单在交易所用的定位
            field.ExchangeID = "";
            field.OrderSysID = "";

            //field.OrderActionRef = 0;
            //field.RequestID     = 0;

            ctpTdApi.ReqOrderAction(field, requestID++);
        }


        /******************************** 查询函数 ********************************/

        /// <summary>
        /// 请求查询成交
        /// </summary>
        public int QryTrade()
        {
            CThostFtdcQryTradeField field = new CThostFtdcQryTradeField();

            field.BrokerID = this.account.Broker.Code;
            field.InvestorID = this.account.Number;

            return ctpTdApi.ReqQryTrade(field, requestID++);
        }

        /// <summary>
        /// 请求查询报单
        /// </summary>
        public int QryOrder()
        {
            CThostFtdcQryOrderField field = new CThostFtdcQryOrderField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;

            return ctpTdApi.ReqQryOrder(field, requestID++);
        }

        /// <summary>
        /// 查询资金账户
        /// </summary>
        public int QryTradingAccount()
        {
            CThostFtdcQryTradingAccountField field = new CThostFtdcQryTradingAccountField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;

            return ctpTdApi.ReqQryTradingAccount(field, requestID++);
        }

        /// <summary>
        /// 查询合约
        /// </summary>
        /// <param name="instrumentID">合约代码（不填则查所有合约）</param>
        public int QryInstrument(string instrumentID)
        {
            CThostFtdcQryInstrumentField field = new CThostFtdcQryInstrumentField();

            field.InstrumentID = instrumentID;

            return ctpTdApi.ReqQryInstrument(field, requestID++);
        }

        /// <summary>
        /// 请求查询投资者持仓
        /// </summary>
        /// <param name="instrumentID">合约代码（不填则查询所有合约的持仓情况）</param>
        public int QryInvestorPosition(string instrumentID = "")
        {
            CThostFtdcQryInvestorPositionField field = new CThostFtdcQryInvestorPositionField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;
            field.InstrumentID = instrumentID;

            return ctpTdApi.ReqQryInvestorPosition(field, requestID++);
        }

        /// <summary>
        /// 请求查询投资者持仓明细
        /// </summary>
        /// <param name="instrumentID">合约代码（不填则查询所有合约的持仓情况）</param>
        public int QryInvestorPositionDetail(string instrumentID = "")
        {
            CThostFtdcQryInvestorPositionDetailField field = new CThostFtdcQryInvestorPositionDetailField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;
            field.InstrumentID = instrumentID;

            return ctpTdApi.ReqQryInvestorPositionDetail(field, requestID++);
        }

        /// <summary>
        /// 请求查询投资者组合持仓明细
        /// </summary>
        /// <param name="instrumentID">合约代码（不填则查询所有合约的持仓情况）</param>
        public int QryInvestorPositionCombineDetail(string combInstrumentID = "")
        {
            CThostFtdcQryInvestorPositionCombineDetailField field = new CThostFtdcQryInvestorPositionCombineDetailField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;
            field.CombInstrumentID = combInstrumentID;

            return ctpTdApi.ReqQryInvestorPositionCombineDetail(field, requestID++);
        }

        /// <summary>
        /// 查询投资者结算确认结果
        /// </summary>
        public int QrySettlementConfirmInfo()
        {
            CThostFtdcQrySettlementInfoConfirmField field = new CThostFtdcQrySettlementInfoConfirmField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;

            return ctpTdApi.ReqQrySettlementInfoConfirm(field, requestID++);
        }

        /// <summary>
        /// 确认投资者结算
        /// </summary>
        public int ReqSettlementConfirmInfo()
        {
            CThostFtdcSettlementInfoConfirmField field = new CThostFtdcSettlementInfoConfirmField();

            field.BrokerID = this.account.BrokerCode;
            field.InvestorID = this.account.Number;
            field.ConfirmDate = DateTime.Now.ToString("yyyyMMdd");
            field.ConfirmTime = DateTime.Now.ToString("HH:mm:ss");

            return ctpTdApi.ReqSettlementInfoConfirm(field, requestID++);
        }


        /******************************** Private ********************************/

        /// <summary>
        /// 要刷新的合约信息列表
        /// </summary>
        private List<CThostFtdcInstrumentField> instrumentInfos;

        /// <summary>
        /// 刷新合约信息（每天确认结算单后做一次）
        /// </summary>
        private void FlushInstrumentInfo(CThostFtdcInstrumentField field, bool bIsLast)
        {
            if (instrumentInfos == null)
                instrumentInfos = new List<CThostFtdcInstrumentField>(300);

            if (field != null)
                instrumentInfos.Add(field);

            if (bIsLast)
            {
                WAF.EntityFramework.EntitySession dbo = new WAF.EntityFramework.EntitySession();
                dbo.OpenConnection();
                dbo.BeginTransaction();

                WfhTrader.Core.Entity.CtpInstrument instrument;

                try
                {
                    //删除所有合约信息
                    dbo.DbAccess.ExecuteNonQuery("DELETE FROM CtpInstrument");

                    //更新合约信息
                    Type entityType = typeof(WfhTrader.Core.Entity.CtpInstrument);
                    Type fieldType = typeof(CThostFtdcInstrumentField);

                    PropertyInfo[] pInfos = entityType.GetProperties();

                    foreach (CThostFtdcInstrumentField ctpField in instrumentInfos)
                    {
                        instrument = new WfhTrader.Core.Entity.CtpInstrument();

                        foreach (PropertyInfo pInfo in pInfos)
                        {
                            PropertyInfo property = fieldType.GetProperty(pInfo.Name);

                            if (property != null)
                                pInfo.SetValue(instrument, property.GetValue(ctpField, null), null);
                        }

                        dbo.Insert(instrument);
                    }

                    dbo.CommitTtransaction();

                    //不重复刷新
                    //TradeManager.GetInstance().IsUpdateInstrument = true;
                }
                catch (Exception ex)
                {
                    dbo.RollbackTtransaction();
                }
                finally
                {
                    dbo.CloseConnection();
                }
            }
        }


        /******************************** 回调事件 ********************************/

        /// <summary>
        /// 初始化TdApi对象并注册回调事件
        /// </summary>
        private void Init()
        {
            //初始化实例
            ctpTdApi = new CtpTdApi();

            //从数据库中读取前置机地址
            WAF.DAO.DbParameters parameters = new WAF.DAO.DbParameters();
            parameters.Add("@Purpose", (int)this.account.PurposeType, System.Data.DbType.Int32);
            parameters.Add("@Type", (int)FrontType.Trade, System.Data.DbType.Int32);
            CtpFrontAddress[] fronts = EntityAction.Select<CtpFrontAddress>("SELECT Address FROM CtpFrontAddress WHERE Purpose=@Purpose AND Type=@Type", parameters);

            //注册前置机地址
            foreach (CtpFrontAddress front in fronts)
                ctpTdApi.RegisterFront(front.Address);

            //注册事件
            ctpTdApi.CtpTdEvents.OnFrontConnected += this.OnFrontConnected;                //连接请求响应
            ctpTdApi.CtpTdEvents.OnRspUserLogin   += this.OnRspUserLogin;                  //用户登录响应

            ctpTdApi.CtpTdEvents.OnRtnOrder += this.OnRtnOrder;                            //报单通知
            ctpTdApi.CtpTdEvents.OnRtnTrade += this.OnRtnTrade;                            //成交通知
            ctpTdApi.CtpTdEvents.OnRtnTradingNotice += this.OnRtnTradingNotice;            //交易通知

            ctpTdApi.CtpTdEvents.OnRspOrderInsert += this.OnRspOrderInsert;                //报单录入请求响应
            ctpTdApi.CtpTdEvents.OnRspOrderAction += this.OnRspOrderAction;                //报单操作请求响应

            ctpTdApi.CtpTdEvents.OnErrRtnOrderInsert += this.OnErrRtnOrderInsert;          //报单录入错误回报
            ctpTdApi.CtpTdEvents.OnErrRtnOrderAction += this.OnErrRtnOrderAction;          //报单操作错误回报

            ctpTdApi.CtpTdEvents.OnRspQryInstrument      += this.OnRspQryInstrument;       //请求查询合约响应
            ctpTdApi.CtpTdEvents.OnRspQryDepthMarketData += this.OnRspQryDepthMarketData;  //请求查询行情响应

            ctpTdApi.CtpTdEvents.OnRspQryOrder += this.OnRspQryOrder;                      //请求查询报单响应
            ctpTdApi.CtpTdEvents.OnRspQryTrade += this.OnRspQryTrade;                      //请求查询成交响应
            ctpTdApi.CtpTdEvents.OnRspQryTradingAccount += this.OnRspQryTradingAccount;    //请求查询资金账户响应

            ctpTdApi.CtpTdEvents.OnRspQrySettlementInfo += this.OnRspQrySettlementInfo;         //查询投资者结算结果响应
            ctpTdApi.CtpTdEvents.OnRspSettlementInfoConfirm += this.OnRspSettlementInfoConfirm;     //确认投资者结算结果响应
            ctpTdApi.CtpTdEvents.OnRspQrySettlementInfoConfirm += this.OnRspQrySettlementInfoConfirm;  //请求查询结算信息确认响应

            ctpTdApi.CtpTdEvents.OnRspQryInvestor += this.OnRspQryInvestor;                                            //请求查询投资者响应
            ctpTdApi.CtpTdEvents.OnRspQryInvestorPosition += this.OnRspQryInvestorPosition;                            //请求查询投资者持仓响应
            ctpTdApi.CtpTdEvents.OnRspQryInvestorPositionDetail += this.OnRspQryInvestorPositionDetail;                //请求查询投资者持仓明细响应
            ctpTdApi.CtpTdEvents.OnRspQryInvestorPositionCombineDetail += this.OnRspQryInvestorPositionCombineDetail;  //请求查询投资者组合持仓明细响应

            ctpTdApi.CtpTdEvents.OnRtnInstrumentStatus += this.OnRtnInstrumentStatus;       //合约交易状态通知

            ctpTdApi.SubscribePrivateTopic(1);
            ctpTdApi.SubscribePublicTopic(1);

            ctpTdApi.Init();
            Task task = Task.Factory.StartNew(ctpTdApi.Join);
        }

        //连接请求响应
        private void OnFrontConnected()
        {
            CThostFtdcReqUserLoginField loginField = new CThostFtdcReqUserLoginField();

            loginField.BrokerID = this.account.BrokerCode;
            loginField.UserID = this.account.Number;
            loginField.Password = account.Password;

            ctpTdApi.ReqUserLogin(loginField, requestID++);
        }

        //用户登录请求响应(确认结算信息)
        private void OnRspUserLogin(CThostFtdcRspUserLoginField rspUserLoginfield, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (rspUserLoginfield.TradingDay != "")
            {
                frontID = rspUserLoginfield.FrontID;
                sessionID = rspUserLoginfield.SessionID;
                orderRef = int.Parse(rspUserLoginfield.MaxOrderRef);

                //查询并确认结算信息
                QrySettlementConfirmInfo();
            }
        }

        /// <summary>
        /// 报单通知
        /// </summary>
        public event OnRtnOrderDelegate RtnOrder;
        public delegate void OnRtnOrderDelegate(CThostFtdcOrderField pOrder);

        private void OnRtnOrder(CThostFtdcOrderField pOrder)
        {
            foreach (Order order in orders)
            {
                if (order.OrderRef == pOrder.OrderRef)
                {
                    order.ExchangeID = pOrder.ExchangeID;
                    order.OrderSysID = pOrder.OrderSysID;
                    break;
                }
            }

            if (RtnOrder != null)
                RtnOrder(pOrder);
        }

        /// <summary>
        /// 成交通知
        /// </summary>
        public event OnRtnTradeDelegate RtnTrade;
        public delegate void OnRtnTradeDelegate(CThostFtdcTradeField pTrade);

        private void OnRtnTrade(CThostFtdcTradeField pTrade)
        {
            CtpOrder removeOrder = null;

            foreach (CtpOrder order in orders)
            {
                if (pTrade.ExchangeID == order.ExchangeID && pTrade.OrderSysID == order.OrderSysID)
                {
                    PositionManager positionManager = PositionManager.GetInstance();

                    //开仓
                    if (pTrade.OffsetFlag == OffsetFlagEnum.Open)
                    {
                        order.Position.UpdateOpenPosition(order.PositionDetail, DateTime.Parse(pTrade.TradeTime), pTrade.Price, pTrade.Volume);
                    }
                    //平仓
                    else if (pTrade.OffsetFlag == OffsetFlagEnum.Close || pTrade.OffsetFlag == OffsetFlagEnum.CloseToday || pTrade.OffsetFlag == OffsetFlagEnum.CloseYesterday)
                    {
                        order.Position.UpdateClosePosition(DateTime.Parse(pTrade.TradeTime), pTrade.Price, pTrade.Volume);
                    }

                    order.Volume -= pTrade.Volume;
                    if (order.Volume <= 0) removeOrder = order;

                    break;
                }
            }

            //移除已经成交完成的委托单
            if (removeOrder != null) orders.Remove(removeOrder);

            if (RtnTrade != null)
                RtnTrade(pTrade);
        }

        /// <summary>
        /// 交易通知
        /// </summary>
        public event OnRtnTradingNoticeDelegate RtnTradingNotice;
        public delegate void OnRtnTradingNoticeDelegate(CThostFtdcTradingNoticeInfoField pTradingNoticeInfo);

        private void OnRtnTradingNotice(CThostFtdcTradingNoticeInfoField pTradingNoticeInfo)
        {
            if (RtnTradingNotice != null)
                RtnTradingNotice.BeginInvoke(pTradingNoticeInfo, null, null);
        }

        /// <summary>
        /// 报单录入请求响应
        /// </summary>
        public event OnRspOrderInsertDelegate RspOrderInsert;
        public delegate void OnRspOrderInsertDelegate(CThostFtdcInputOrderField pInputOrder, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspOrderInsert(CThostFtdcInputOrderField pInputOrder, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspOrderInsert != null)
                RspOrderInsert.BeginInvoke(pInputOrder, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 报单操作请求响应
        /// </summary>
        public event OnRspOrderActionDelegate RspOrderAction;
        public delegate void OnRspOrderActionDelegate(CThostFtdcInputOrderActionField pInputOrderAction, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspOrderAction(CThostFtdcInputOrderActionField pInputOrderAction, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspOrderAction != null)
                RspOrderAction.BeginInvoke(pInputOrderAction, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 报单录入错误回报
        /// </summary>
        public event OnErrRtnOrderInsertDelegate ErrRtnOrderInsert;
        public delegate void OnErrRtnOrderInsertDelegate(CThostFtdcInputOrderField pInputOrder, CThostFtdcRspInfoField pRspInfo);

        private void OnErrRtnOrderInsert(CThostFtdcInputOrderField pInputOrder, CThostFtdcRspInfoField pRspInfo)
        {
            if (ErrRtnOrderInsert != null)
                ErrRtnOrderInsert.BeginInvoke(pInputOrder, pRspInfo, null, null);
        }

        /// <summary>
        /// 报单操作错误回报
        /// </summary>
        public event OnErrRtnOrderActionDelegate ErrRtnOrderAction;
        public delegate void OnErrRtnOrderActionDelegate(CThostFtdcOrderActionField pOrderAction, CThostFtdcRspInfoField pRspInfo);

        private void OnErrRtnOrderAction(CThostFtdcOrderActionField pOrderAction, CThostFtdcRspInfoField pRspInfo)
        {
            if (ErrRtnOrderAction != null)
                ErrRtnOrderAction.BeginInvoke(pOrderAction, pRspInfo, null, null);
        }

        /// <summary>
        /// 请求查询合约响应
        /// </summary>
        public event OnRspQryInstrumentDelegate RspQryInstrument;
        public delegate void OnRspQryInstrumentDelegate(CThostFtdcInstrumentField pInstrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryInstrument(CThostFtdcInstrumentField pInstrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            //如果没有更新过合约信息，则更新数据库中的合约信息
            //if (!TradeManager.GetInstance().IsUpdateInstrument)
                //FlushInstrumentInfo(pInstrument, bIsLast);

            if (RspQryInstrument != null)
                RspQryInstrument.BeginInvoke(pInstrument, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询报单响应
        /// </summary>
        public event OnRspQryOrderDelegate RspQryOrder;
        public delegate void OnRspQryOrderDelegate(CThostFtdcOrderField pOrder, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryOrder(CThostFtdcOrderField pOrder, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspQryOrder != null)
                RspQryOrder.BeginInvoke(pOrder, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询成交响应
        /// </summary>
        public event OnRspQryTradeDelegate RspQryTrade;
        public delegate void OnRspQryTradeDelegate(CThostFtdcTradeField pTrade, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryTrade(CThostFtdcTradeField pTrade, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspQryTrade != null)
                RspQryTrade.BeginInvoke(pTrade, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询资金账户响应
        /// </summary>
        public event OnRspQryTradingAccountDelegate RspQryTradingAccount;
        public delegate void OnRspQryTradingAccountDelegate(CThostFtdcTradingAccountField pTradingAccount, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (pTradingAccount != null)
            {
                if (RspQryTradingAccount != null)
                    RspQryTradingAccount.BeginInvoke(pTradingAccount, pRspInfo, nRequestID, bIsLast, null, null);
            }
        }

        /// <summary>
        /// 查询结算信息响应
        /// </summary>
        public event OnRspQrySettlementInfoDelegate RspQrySettlementInfo;
        public delegate void OnRspQrySettlementInfoDelegate(CThostFtdcSettlementInfoField pSettlementInfo, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQrySettlementInfo(CThostFtdcSettlementInfoField pSettlementInfo, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspQrySettlementInfo != null)
                RspQrySettlementInfo.BeginInvoke(pSettlementInfo, pRspInfo, nRequestID, bIsLast, null, null);
        }

        //查询投资者结算确认结果响应
        private void OnRspQrySettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField pSettlementInfoConfirm, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            //如果结果为空则说明没有确认过结果
            if (bIsLast && pSettlementInfoConfirm == null)
                ReqSettlementConfirmInfo();
        }

        /// <summary>
        /// 确认投资者结算结果响应
        /// </summary>
        public event OnRspSettlementInfoConfirmDelegate RspSettlementInfoConfirm;
        public delegate void OnRspSettlementInfoConfirmDelegate(CThostFtdcSettlementInfoConfirmField pSettlementInfoConfirm, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField pSettlementInfoConfirm, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            //每天确认结算单后更新合约信息
            QryInstrument("");

            if (RspSettlementInfoConfirm != null)
                RspSettlementInfoConfirm.BeginInvoke(pSettlementInfoConfirm, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询投资者响应
        /// </summary>
        public event OnRspQryInvestorDelegate RspQryInvestor;
        public delegate void OnRspQryInvestorDelegate(CThostFtdcInvestorField pInvestor, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryInvestor(CThostFtdcInvestorField pInvestor, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspQryInvestor != null)
                RspQryInvestor.BeginInvoke(pInvestor, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询投资者持仓响应
        /// </summary>
        public event OnRspQryInvestorPositionDelegate RspQryInvestorPosition;
        public delegate void OnRspQryInvestorPositionDelegate(CThostFtdcInvestorPositionField pInvestorPosition, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private List<CThostFtdcInvestorPositionField> positions = new List<CThostFtdcInvestorPositionField>();
        private void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField pInvestorPosition, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (pInvestorPosition != null)
                positions.Add(pInvestorPosition);

            if (bIsLast)
            {
                //this.ctpAccount.Positions = positions;
                positions = new List<CThostFtdcInvestorPositionField>();
            }

            if (RspQryInvestorPosition != null)
                RspQryInvestorPosition.BeginInvoke(pInvestorPosition, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询投资者持仓明细响应
        /// </summary>
        public event OnRspQryInvestorPositionDetailDelegate RspQryInvestorPositionDetail;
        public delegate void OnRspQryInvestorPositionDetailDelegate(CThostFtdcInvestorPositionDetailField pInvestorPositionDetail, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private List<CThostFtdcInvestorPositionDetailField> positionDetails = new List<CThostFtdcInvestorPositionDetailField>();
        private void OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailField pInvestorPositionDetail, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (pInvestorPositionDetail != null && pInvestorPositionDetail.Volume != 0)
                positionDetails.Add(pInvestorPositionDetail);

            if (bIsLast)
            {
                //this.ctpAccount.PositionDetails = positionDetails;
                positionDetails = new List<CThostFtdcInvestorPositionDetailField>();
            }

            if (RspQryInvestorPositionDetail != null)
                RspQryInvestorPositionDetail.BeginInvoke(pInvestorPositionDetail, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询投资者组合持仓明细响应
        /// </summary>
        public event OnRspQryInvestorPositionCombineDetailDelegate RspQryInvestorPositionCombineDetail;
        public delegate void OnRspQryInvestorPositionCombineDetailDelegate(CThostFtdcInvestorPositionCombineDetailField pInvestorPositionCombineDetail, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryInvestorPositionCombineDetail(CThostFtdcInvestorPositionCombineDetailField pInvestorPositionCombineDetail, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspQryInvestorPositionCombineDetail != null)
                RspQryInvestorPositionCombineDetail.BeginInvoke(pInvestorPositionCombineDetail, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 请求查询行情响应
        /// </summary>
        public event OnRspQryDepthMarketDataDelegate RspQryDepthMarketData;
        public delegate void OnRspQryDepthMarketDataDelegate(CThostFtdcDepthMarketDataField pDepthMarketData, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast);

        private void OnRspQryDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {
            if (RspQryDepthMarketData != null)
                RspQryDepthMarketData.BeginInvoke(pDepthMarketData, pRspInfo, nRequestID, bIsLast, null, null);
        }

        /// <summary>
        /// 合约交易状态通知
        /// </summary>
        public event OnRtnInstrumentStatusDelegate RtnInstrumentStatus;
        public delegate void OnRtnInstrumentStatusDelegate(CThostFtdcInstrumentStatusField pInstrumentStatus);

        private void OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField pInstrumentStatus)
        {
            if (RtnInstrumentStatus != null)
                RtnInstrumentStatus.BeginInvoke(pInstrumentStatus, null, null);
        }
    }
}
